package chapter6_2_condition;

import javafx.beans.binding.ObjectExpression;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class BlockingQueue {

    final Object[] items; // 缓冲数组
    final ReentrantLock lock = new ReentrantLock(); // 非公平独占锁
    final Condition notFull = lock.newCondition(); // 未满条件
    final Condition notEmpty = lock.newCondition(); // 未空条件
    private int putIdx; // 添加操作的指针
    private int takeIdx; // 获取操作的指针
    private int count; // 队列中元素个数

    public BlockingQueue(int capacity) {
        if(capacity < 0) throw new IllegalArgumentException();
        items = new Object[capacity];
    }

    // 插入
    public void put(Object item) throws InterruptedException {
        try {
            lock.lock(); // 上锁
            while (items.length == count) { // 满了
                notFull.await(); // 其他插入线程阻塞起来
            }
            enqueue(item); // 没满就可以入队
        } finally {
            lock.unlock(); // 不要忘记解锁
        }
    }
    private void enqueue(Object item) {
        items[putIdx] = item;
        if (++putIdx == items.length) putIdx = 0;
        count++;
        notEmpty.signal(); // 叫醒获取的线程
    }

    // 获取
    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                notEmpty.await();// 阻塞其他获取线程
            }
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

    private Object dequeue() {
        Object x = items[takeIdx];
        items[takeIdx] = null;
        if (++takeIdx == items.length) takeIdx = 0;
        count--;
        notFull.signal(); // 叫醒其他的插入线程
        return x;
    }
}

class Test {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue queue = new BlockingQueue(2);
        queue.put(1);
        queue.put(2);

        System.out.println(queue);
        queue.take();
        queue.take();
        queue.take();
    }
}